Nginx 反向代理

8/11/2022 nginx

# Nginx 反向代理

# 概念定义

  • 反向代理服务器介于用户和真实服务器之间,提供请求和响应的中转服务
  • 对用户而言,访问反向代理服务器就是访问真实服务器
  • 反向代理可以有效降低服务器的负载消耗,提高效率

image-20220810030131589

假设现在有一个用户和一个真实服务器的话

用户通常是在互联网之中的,而真实服务器通常部署在内网之中的,因此用户去直接访问是无法访问到的。

所以我们通常会在中间加一个代理服务器,代理服务器通常是位于整个公司业务系统的一个边缘节点。这个边缘节点既可以和内网保持联通,同时我们还会配置一个公网的ip地址,确保我们的域名可以解析到这台代理服务器对应的ip地址,从而确保用户的请求可以到达这台代理服务器。

这个时候我们的代理服务器充当的就是一个中间人的角色,这个时候加入用户想要去访问真实服务器地址的时候,他其实并不知道你的真实服务器在哪里,他会把一些 http或其他的 Request的请求转发给代理服务器,代理服务器会再转发给真实服务器。

真实服务器收到请求后会把返回的数据传递给代理服务器,再由于代理服务器转发给用户。

# 反向代理优势

  • 隐藏真实服务器

    可部署在内网不直接出现在互联网上,减低了攻击的可能性

  • 便于横向扩充后端动态服务

    当一台服务器性能不够时,可以使用多台服务器;负载均衡

  • 动静分离,提高系统健壮性

    动静分离是指在web服务器架构中,将静态页面与动态页面和静态内容接口或动态内容接口分开不 同系统访问的架构设计方法,进而提升整个服务访问性能和维护性

# WEB资源分类

image-20220810031413661

# WEB请求图解

在早期互联网,可能只有一台服务器用来相应静态请求和动态请求,静态资源和动态资源部署在单台服务器上,前后端是耦合在一块的。

image-20220810032137639

随着前后端分离,动态请求和静态请求就实现了分开。

image-20220810031558486

当url 包含静态请求时,nginx 自身是能够处理静态资源的,请求静态资源时能够在磁盘文件系统中读取返回。

当 url 包含动态请求时,nginx 自身是没法处理的,这个时候会将动态请求反向代理到后端的动态资源服务器,nginx 拿到 动态资源服务器返回的结果后会一并的返回给用户。

当并发量处理不来时,可以添加多台动态资源服务器,提高整个系统的吞吐量

image-20220810032747066

# nginx 反向代理支持协议

nginx作为反向代理时可以与应用服务器交互时可以使用的协议

image-20220810034129763

# upstream模块

# 基本功能

  • upstream模块用于定义上游服务的相关信息
  • 默认已被编译进 nginx
  • 禁用须通过-- without-http_upstream_module参数

image-20220810035643669

# 相关指令集

image-20220810035752225

image-20220810035809711

# 指令集使用

# upstream

语法: upstream name { ...... }
默认值: 无
上下文: http
示例: upstream {
            ......
            ......
              }
1
2
3
4
5
6
7

# server

语法: server address [parameters];
默认值: 无
上下文: upstream
1
2
3

image-20220810040834921

# keepalive

限制每个 worker 子进程与上游服务器空闲长链接的最大数量

语法: keepalive connections
默认值: 无
上下文: upstream
示例: keepalive 16;
1
2
3
4
5
6

# keepalive_requests

单个长链接可以处理的最多 HTTP 请求个数

语法: keepalive_requests number;
默认值: keepalive_requests 100;
上下文: upstream
1
2
3
4
5

# keepalive_timeout

空闲长链接的最长保持时间

语法: keepalive_timeout time;
默认值: keepalive_timeout 60s;
上下文: upstream
1
2
3
4
5

# queue

所有上游服务器不可用时,请求会被放到队列中等待

语法: queue number[timeout=time];
默认值: 无
上下文: upstream
示例: queue 100 timeout =30s;
1
2
3
4
5
6

# 配置示例

upstream back_end {
   server 127.0.0.1:8080 weight=3 max_conns=1000 fail_timeout=10s
max_fails=2;
   keepalive 32;
   keepalive_requests 50;
   keepalive_timeout 30s;
}
1
2
3
4
5
6
7

# 配置一个可用的上游应用程序服务器

服务器A

配置文件路径 一般在 /etc/nginx/nginx.conf

# nginx.conf 文件
#在配置文件添加以下一句
#意思是在nginx 目录下创建 conf.d 目录把.conf 结尾文件包含进来
include /etc/nginx/conf.d/*.conf;
1
2
3
4

# 创建名称为 app_server.conf 的配置文件

#进入conf.d目录
cd /etc/nginx/conf.d 
#创建配置
vim app_serve.conf

示例:
server {
        listen 8080;
        server_name localhost;
        
        localtion /proxy/ { 
               root /opt/nginx/html/app;
               index proxy.html;
        }
}
#保存
:wq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 创建一个模拟动态服务的脚本文件

#cd 到项目文件夹下
cd /opt/nginx/html/app/proxy
#写一个产生随机数的脚本
vim create_random_number.sh
示例:
#!/bin/bash
#挂载目录
DIR=/opt/nginx/html/app/proxy
#指定文件
FILE=proxy.html
#写一个死循环指定时间执行一次
while true;do
      echo "Application Server,This time create number: $RANDOM" > $DIR/$FILE
      sleep 1
done

#运行脚本
nohup sh create_random_number.sh
# 可以查看文件是否变化
 cat proxy.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 测试结果

#检查是否正确
/usr/sbin/nginx -t
#重启服务
/usr/sbin/nginx -s reload
#查看监听端口
ss -tnl
#测试服务是否可用
curl localhost:8080/proxy/
1
2
3
4
5
6
7
8

# 配置 nginx反向代理实例

# proxy_pass 指令

  • 由 http_proxy 模块提供(ngx_http_proxy_module)
  • 默认已经被编译进 nginx
  • 禁用须通过 without-http_proxy_module

# 语法结构

语法: proxy_pass URL
默认值: 无
上下文:location、if、limit_except
示例一: proxy_pass http://127.0.0.1:8080
示例二: proxy_pass http://127.0.0.1:8090/proxy
1
2
3
4
5

# URL 参数原则

  • URL 必须以 http 或 https 开头
  • URL 中可以携带变量
  • URL 中是否带 URI,会直接影响发往上游请求的 URL

# 反向代理配置

服务器B 反向代理 应用服务器 A

#进入存放配置的文件夹
cd /opt/nginx/conf.d/
#创建一个配置文件
vim proxy.conf

#编辑配置文件
#定义上游服务器信息
upstream back_end{
        server 应用服务器A的IP+端口或域名 weight=2 max_conns=1000 fail_timeout=10s max_fails=3;
        keepalive 32;
        keepalive_requests 80;
        keepalive_timeout 20s;
}

server {
        listen 80;
        server_name  本机域名
        
        location /proxy {
          proxy_pass http://back_end/proxy;
        }
}

#保存,测试配置
/opt/nginx/sbin/nginx -t
#重启服务
/opt/nginx/sbin/nginx -s reload
#测试
#将本机域名 编辑添加至 hosts
vim /etc/hosts
#使用curl测试是否能通过反向代理访问应用服务器A的内容
curl 本地域名/proxy/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 两种常见用法

  1. proxy_pass http://192.168.184.20:8080
  2. proxy_pass http://192.168.184.20:8080/
  • 代理到上游服务器的 URL结尾是否有必要加 /

  • 带 / 和不带 / 用法区别

不带 / 意味着 Nginx 不会修改用户 URL ,而是透传给上游的应用服务器

location /bbs/{
       proxy_pass http://127.0.0.1:8080;
}
1
2
3
用户请求 URL:/bbs/abc/test.html 
1
请求到达 Nginx 的 URL: /bbs/abc/test.html
1
请求到达上游应用服务器的URL : /bbs/abc/test.html
1

带 / 意味着 Nginx 会修改用户 URL ,修改方法:将location 后的URL从用户 URL 中删除

location /bbs/{
       proxy_pass http://127.0.0.1:8080/;
}
1
2
3
用户请求 URL:/bbs/abc/test.html 
1
请求到达 Nginx 的 URL: /bbs/abc/test.html
1
请求到达上游应用服务器的URL : /abc/test.html
1

# 代理场景下 nginx 如何更改往上游的请求

image-20220810174351138

image-20220810174427569

image-20220810174445616